/*****************************************************************************/
/*                                                                           */
/*    Domino Operation System Driver Module                                  */
/*                                                                           */
/*    Copyright (C) 2008 Laszlo Arvai                                        */
/*                                                                           */
/*    ------------------------------------------------------------------     */
/*    Module: drvUART - UART Driver                                          */
/*                                                                           */
/*    IOconfig declarations:                                                 */
/*      sysPBCLK_FREQUENCY = CPU clock used for baud rate calculations [Hz]  */
/*      UART1_BAUD_RATE = Desired baud UART1 [baud]                          */
/*      UART2_BAUD_RATE = Desired baud rate for UART2 [baud]                 */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include <drvUART.h>
#include <krnlUART.h>
#include "drvIOConfig.h"

///////////////////////////////////////////////////////////////////////////////
// Defines
#define CALCULATE_UART_BAUD_RATE(baud_rate)	(((sysPBCLK_FREQUENCY)/16/(baud_rate)-1))

#ifdef UART_BAUD_RATE
#define UART1_BAUD_RATE UART_BAUD_RATE
#define UART2_BAUD_RATE UART_BAUD_RATE
#define UART1A_BAUD_RATE UART_BAUD_RATE
#endif

///////////////////////////////////////////////////////////////////////////////
// Module global variables

/*****************************************************************************/
/* UART 1A Functions                                                          */
/*****************************************************************************/
#ifdef drvUART1A_ENABLED 

///////////////////////////////////////////////////////////////////////////////
// Initialize UART driver
void drvUART1Init(void)
{
	// Enable UART
	UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
	UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
	UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
	UARTSetDataRate(UART1, sysPBCLK_FREQUENCY, UART1A_BAUD_RATE);
	UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
	
	// Enable interrupts
  INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
  INTEnable(INT_SOURCE_UART_TX(UART1), INT_DISABLED);
	INTSetVectorPriority(INT_VECTOR_UART(UART1), INT_PRIORITY_LEVEL_2);
	INTSetVectorSubPriority(INT_VECTOR_UART(UART1), INT_SUB_PRIORITY_LEVEL_0);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte on UART
void drvUART1SendCharacter( dosChar in_byte )
{
	UARTSendDataByte(UART1, in_byte);
}

///////////////////////////////////////////////////////////////////////////////
// Enable transmit interrupt
void drvUART1EnableTransmitInterrupt(void)
{
	INTEnable(INT_SOURCE_UART_TX(UART1), INT_ENABLED);
}

///////////////////////////////////////////////////////////////////////////////
// Disable transmit interrupt
void drvUART1DisableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART1), INT_DISABLED);
}

///////////////////////////////////////////////////////////////////////////////
// UART 1 interrupt handler
void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)
{
	// Is this an RX interrupt?
	if(INTGetFlag(INT_SOURCE_UART_RX(UART1)))
	{
		// Process received data
		krnlUART1AReceiveInterrupt(UARTGetDataByte(UART1));

		// Clear the RX interrupt Flag
		INTClearFlag(INT_SOURCE_UART_RX(UART1));
	}

	// Handle TX interrupt
	if(INTGetEnable(INT_U1TX) && INTGetFlag(INT_SOURCE_UART_TX(UART1)))
	{
  	krnlUART1ATransmitInterrupt();

		INTClearFlag(INT_SOURCE_UART_TX(UART1));
	}
}
#endif

/*****************************************************************************/
/* UART 1 Functions                                                          */
/*****************************************************************************/

#ifdef drvUART1_ENABLED 

///////////////////////////////////////////////////////////////////////////////
// Initialize UART driver
void drvUART1Init(void)
{
	UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY );
	UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL |UART_INTERRUPT_ON_RX_NOT_EMPTY);
	UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
	UARTSetDataRate(UART1,  sysPBCLK_FREQUENCY, UART1_BAUD_RATE);
	UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

	INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
  INTSetVectorPriority(INT_VECTOR_UART(UART1), INT_PRIORITY_LEVEL_2);
  INTSetVectorSubPriority(INT_VECTOR_UART(UART1), INT_SUB_PRIORITY_LEVEL_0);
}

///////////////////////////////////////////////////////////////////////////////
// Opens UART 1
void drvUART1Open(void)
{
	drvUART1Init();
}

///////////////////////////////////////////////////////////////////////////////
// Closes UART1
void drvUART1Close(void)
{
  INTEnable(INT_SOURCE_UART_RX(UART1), INT_DISABLED);
  INTEnable(INT_SOURCE_UART_TX(UART1), INT_DISABLED);
	UARTEnable(UART1, UART_DISABLE);
}

///////////////////////////////////////////////////////////////////////////////
// Sets baud rate
void drvUART1SetBaudRate(dosWord in_baud_rate)
{
	UARTSetDataRate(UART1, sysPBCLK_FREQUENCY, in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte on UART
void drvUART1SendCharacter( dosChar in_byte )
{
	UARTSendDataByte(UART1, in_byte);
}

///////////////////////////////////////////////////////////////////////////////
// Enable transmit interrupt
void drvUART1EnableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART1), INT_ENABLED);
}

///////////////////////////////////////////////////////////////////////////////
// Disable transmit itnerrupt
void drvUART1DisableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART1), INT_DISABLED);
}

///////////////////////////////////////////////////////////////////////////////
// UART 1 interrupt handler
void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)
{
	dosByte data;

	// Handle RX interrupt
  if(INTGetFlag(INT_U1RX))
  {
		// get data byte
		data = UARTGetDataByte(UART1);

    // Clear the RX interrupt Flag
		INTClearFlag(INT_U1RX);

    // Process received data
		krnlUART1ReceiveInterrupt(data);
   }

   // Handle TX interrupt
   if(INTGetFlag(INT_U1TX))
   {
      krnlUART1TransmitInterrupt();

			INTClearFlag(INT_U1TX);
   }
}
#endif

/*****************************************************************************/
/* UART 2 Functions                                                          */
/*****************************************************************************/

#ifdef drvUART2_ENABLED

///////////////////////////////////////////////////////////////////////////////
// Initialize UART driver
void drvUART2Init(void)
{
	UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY );
	UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_NOT_FULL |UART_INTERRUPT_ON_RX_NOT_EMPTY);
	UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
	UARTSetDataRate(UART2,  sysPBCLK_FREQUENCY, UART2_BAUD_RATE);
	UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

	INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
  INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_2);
  INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);
}

///////////////////////////////////////////////////////////////////////////////
// Opens UART
void drvUART2Open(void)
{
	drvUART2Init();
}

///////////////////////////////////////////////////////////////////////////////
// Closes UART
void drvUART2Close(void)
{
  INTEnable(INT_SOURCE_UART_RX(UART2), INT_DISABLED);
  INTEnable(INT_SOURCE_UART_TX(UART2), INT_DISABLED);
	UARTEnable(UART2, UART_DISABLE);
}

///////////////////////////////////////////////////////////////////////////////
// Sets baud rate
void drvUART2SetBaudRate(dosWord in_baud_rate)
{
	UARTSetDataRate(UART2, sysPBCLK_FREQUENCY, in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte on UART
void drvUART2SendCharacter( dosChar in_byte )
{
	UARTSendDataByte(UART2, in_byte);
}

///////////////////////////////////////////////////////////////////////////////
// Enable transmit interrupt
void drvUART2EnableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED);
}

///////////////////////////////////////////////////////////////////////////////
// Disable transmit itnerrupt
void drvUART2DisableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART2), INT_DISABLED);
}

///////////////////////////////////////////////////////////////////////////////
// UART interrupt handler
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)
{
	dosByte data;

	// Handle RX interrupt
  if(INTGetFlag(INT_U2RX))
  {
		// get data byte
		data = UARTGetDataByte(UART2);

    // Clear the RX interrupt Flag
		INTClearFlag(INT_U2RX);

    // Process received data
		krnlUART2ReceiveInterrupt(data);
   }

   // Handle TX interrupt
   if(INTGetFlag(INT_U2TX))
   {
      krnlUART2TransmitInterrupt();

			INTClearFlag(INT_U2TX);
   }
}
#endif

/*****************************************************************************/
/* UART 3 Functions                                                          */
/*****************************************************************************/

#ifdef drvUART3_ENABLED

///////////////////////////////////////////////////////////////////////////////
// Initialize UART driver
void drvUART3Init(void)
{
	UARTConfigure(UART3, UART_ENABLE_PINS_TX_RX_ONLY );
	UARTSetFifoMode(UART3, UART_INTERRUPT_ON_TX_NOT_FULL |UART_INTERRUPT_ON_RX_NOT_EMPTY);
	UARTSetLineControl(UART3, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
	UARTSetDataRate(UART3,  sysPBCLK_FREQUENCY, UART3_BAUD_RATE);
	UARTEnable(UART3, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

	INTEnable(INT_SOURCE_UART_RX(UART3), INT_ENABLED);
  INTSetVectorPriority(INT_VECTOR_UART(UART3), INT_PRIORITY_LEVEL_2);
  INTSetVectorSubPriority(INT_VECTOR_UART(UART3), INT_SUB_PRIORITY_LEVEL_0);
}

///////////////////////////////////////////////////////////////////////////////
// Opens UART
void drvUART3Open(void)
{
	drvUART3Init();
}

///////////////////////////////////////////////////////////////////////////////
// Closes UART
void drvUART3Close(void)
{
  INTEnable(INT_SOURCE_UART_RX(UART3), INT_DISABLED);
  INTEnable(INT_SOURCE_UART_TX(UART3), INT_DISABLED);
	UARTEnable(UART3, UART_DISABLE);
}

///////////////////////////////////////////////////////////////////////////////
// Sets baud rate
void drvUART3SetBaudRate(dosWord in_baud_rate)
{
	UARTSetDataRate(UART3, sysPBCLK_FREQUENCY, in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte on UART
void drvUART3SendCharacter( dosChar in_byte )
{
	UARTSendDataByte(UART3, in_byte);
}

///////////////////////////////////////////////////////////////////////////////
// Enable transmit interrupt
void drvUART3EnableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART3), INT_ENABLED);
}

///////////////////////////////////////////////////////////////////////////////
// Disable transmit itnerrupt
void drvUART3DisableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART3), INT_DISABLED);
}

///////////////////////////////////////////////////////////////////////////////
// UART interrupt handler
void __ISR(_UART_2A_VECTOR, ipl2) IntUart2Handler(void)
{
	dosByte data;

	// Handle RX interrupt
  if(INTGetFlag(INT_U3RX))
  {
		// get data byte
		data = UARTGetDataByte(UART3);

    // Clear the RX interrupt Flag
		INTClearFlag(INT_U3RX);

    // Process received data
		krnlUART3ReceiveInterrupt(data);
   }

   // Handle TX interrupt
   if(INTGetFlag(INT_U3TX))
   {
      krnlUART3TransmitInterrupt();

			INTClearFlag(INT_U3TX);
   }
}
#endif

#ifdef drvUART2_ENABLEDD
///////////////////////////////////////////////////////////////////////////////
// Initialize UART driver
void drvUART2Init(void)
{
	// open uart
	/*OpenUART2(UART_EN | UART_NO_PAR_8BIT | UART_1STOPBIT, // Module is ON
			      UART_TX_ENABLE | UART_INT_TX | UART_RX_ENABLE | UART_INT_RX_CHAR,		        // Enable TX & RX
						CALCULATE_UART_BAUD_RATE(UART2_BAUD_RATE));    // Set baudrate
	 * */

	// Configure uart interrupt
	//ConfigIntUART2( UART_RX_INT_EN | UART_TX_INT_EN | UART_ERR_INT_DIS | UART_INT_PR2 );
}

///////////////////////////////////////////////////////////////////////////////
// Opens UART
void drvUART2Open(void)
{
	drvUART2Init();
}

///////////////////////////////////////////////////////////////////////////////
// Closes UART
void drvUART2Close(void)
{
  INTEnable(INT_SOURCE_UART_RX(UART2A), INT_DISABLED);
  INTEnable(INT_SOURCE_UART_TX(UART2A), INT_DISABLED);
	UARTEnable(UART2A, UART_DISABLE | UART_PERIPHERAL | UART_RX | UART_TX);
}

///////////////////////////////////////////////////////////////////////////////
// Sets baud rate
void drvUART2SetBaudRate(dosWord in_baud_rate)
{
	U2BRG = CALCULATE_UART_BAUD_RATE(in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte on UART
void drvUART2SendCharacter( dosChar in_byte )
{
	U2TXREG = in_byte;
}

///////////////////////////////////////////////////////////////////////////////
// Enable transmit interrupt
void drvUART2EnableTransmitInterrupt(void)
{
	INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED);
}

///////////////////////////////////////////////////////////////////////////////
// Disable transmit itnerrupt
void drvUART2DisableTransmitInterrupt(void)
{
  INTEnable(INT_SOURCE_UART_TX(UART2), INT_DISABLED);
}

///////////////////////////////////////////////////////////////////////////////
// UART 2 interrupt handler
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)
{
	// Handle RX interrupt
	if(mU2RXGetIntFlag())
	{
		// Clear the RX interrupt Flag
	  mU2RXClearIntFlag();

		// Process received data
		krnlUART2ReceiveInterrupt(ReadUART2());
	}

	// Handle TX interrupt
	if( mU2TXGetIntFlag() )
	{
		mU2TXClearIntFlag();
		
	 	krnlUART2TransmitInterrupt();
	}
}

#endif
